package at.jaki.ubb.crawling.appThreads;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.Future;

/**
 * This singleton will run on a separate thread. It contains the common methods
 * of result managers.
 * 
 * @author Attila Jakabfi
 * 
 * @param R generic type of result
 */
public abstract class AbstractResultManager<R> extends AbstractCrawlerThread {

	/**
	 * Set of executing task futures.
	 */
	private final Set<Future<R>> executingTasks = new HashSet<Future<R>>();

	private Set<Future<R>> getExecutingTaskSet() {
		return executingTasks;
	}

	/**
	 * this method will clear the the results. <strong> The waiting results will
	 * be lost</strong>
	 */
	@Override
	protected final void clear() {
		synchronized (AbstractResultManager.class) {
			getExecutingTaskSet().clear();
		}

	}

	@Override
	protected final void doWork() {
		synchronized (AbstractResultManager.class) {
			if (executingTasks.size() > 0) {
				Iterator<Future<R>> iterator = getExecutingTaskSet().iterator();
				while (iterator.hasNext()) {
					Future<R> next = iterator.next();
					if (next.isDone()) {
						iterator.remove();
						resolveDoneTask(next);
					}
				}
			}
		}
	}

	/**
	 * Will be called when a task has bean completed.
	 * 
	 * @param future the {@link Future} object, of the completed task
	 */
	public abstract void resolveDoneTask(Future<R> future);

	/**
	 * Will add a {@link Future} to object, a started task to the executing
	 * tasks set. Once the execution finished this thread will manage the
	 * results.
	 * 
	 * @param future can't be null
	 */
	public void addTask(Future<R> future) {
		synchronized (AbstractResultManager.class) {
			getExecutingTaskSet().add(future);
		}
	}

	/**
	 * @return the number of currently running tasks
	 */
	public int getRunningThreadsCount() {
		return executingTasks.size();
	}
}
